/* --------------------------------------------------------------------------------
 * PropellentNet: Propeller IDE
 * Copyright 2008 - Jason Wood
 * --------------------------------------------------------------------------------
 * POC.cs
 * Parent Control Window.
 * --------------------------------------------------------------------------------
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 * 
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 * --------------------------------------------------------------------------------
 */

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Collections;

using Microsoft.Win32;

namespace PropellentNet_POC
{
    
    public partial class IDE : Form
    {
        
        #region Private
        private FileEditors m_FileEditors;
        #endregion Private
        
        #region De/Constructur
        public IDE()
        {
            InitializeComponent();
        }
        #endregion De/Constructur
        
        #region Events
        private void POC_Load(object sender, EventArgs e)
        {
            
            explorer.browse(Registry.CurrentUser.OpenSubKey(@"Software\ParallaxInc\Propeller\1.0").GetValue("LastUsedDirectory").ToString());
            
            cbbCommonFolders.Items.Add("Propeller Library");
            cbbCommonFolders.Items.Add("Propeller Library - Demos");
            cbbCommonFolders.Items.Add("Manual - Examples");
            
            foreach (string ValueName in Registry.CurrentUser.OpenSubKey(@"Software\ParallaxInc\Propeller\1.0").GetValueNames())
            {
                if (ValueName.IndexOf("File") > 0)
                {
                }
            }
            
            m_FileEditors = new FileEditors(this.tabEditers);
            
            //PropellentNet.SpinInterpreter tmpInt = new PropellentNet.SpinInterpreter(@"C:\temp\hold.spin");
           
        }
        private void explorer_DirectoryChanged(string directoryPath, Image selectedIcon)
        {
            Registry.CurrentUser.OpenSubKey(@"Software\ParallaxInc\Propeller\1.0", true).SetValue("LastUsedDirectory", directoryPath);
            this.cbbCommonFolders.Text = directoryPath;
        }
        private void explorer_BeginExecuteFile(string fileName, ref bool allowIt)
        {
            m_FileEditors.Open(fileName);
            allowIt = false;
        }
        private void POC_FormClosing(object sender, FormClosingEventArgs e)
        {
        }
        private void identifyHardwareToolStripMenuItem_Click(object sender, EventArgs e)
        {
            m_FileEditors.IdentifyHardware();
        }
        private void updateStatusToolStripMenuItem_Click(object sender, EventArgs e)
        {
            m_FileEditors.UpdateStatus(this.trvHierarchy);
        }
        private void loadRAMToolStripMenuItem_Click(object sender, EventArgs e)
        {
            m_FileEditors.LoadRAM();
        }
        private void loadToolStripMenuItem_Click(object sender, EventArgs e)
        {
            m_FileEditors.LoadEEROM();            
        }
        private void rdbDocumentation_CheckedChanged(object sender, EventArgs e)
        {

        }
        private void printPreviewToolStripMenuItem_Click(object sender, EventArgs e)
        {

        }
        private void trvHierarchy_BeforeCollapse(object sender, TreeViewCancelEventArgs e)
        {
            e.Cancel = true;
        }
        private void newToolStripMenuItem_Click(object sender, EventArgs e)
        {
            m_FileEditors.New();
        }
        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            m_FileEditors.Save();
        }
        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {

            m_FileEditors.Open();
            
        }
        private void closeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            m_FileEditors.Close();
        }
        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }
        private void saveAsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            m_FileEditors.SaveAs();
        }
        private void saveAllToolStripMenuItem_Click(object sender, EventArgs e)
        {

        }
        private void closeAllToolStripMenuItem_Click(object sender, EventArgs e)
        {
            m_FileEditors.CloseAll();
        }
        #endregion Events
        
    }
    
    public class FileEditors
    {
        
        #region Private
        private TabControl m_HostControl;
        private EditCtrls m_CurrentEditor;
        private Hashtable m_Editors;
        private int m_HoldUntitledCount = 1;
        private PropellentNet.SpinInterpreter m_CodeInterpreter;
        #endregion Private
        
        #region Structs
        private struct EditCtrls
        {
            public string ControlName;
            public string FilePath;
            public PropellentNet.Propellent Compiler;
            public CodeEditorContainer CodeEditor;
        }
        #endregion Structs
        
        #region Events
        void m_HostControl_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (m_HostControl.SelectedTab != null)
                m_CurrentEditor = (EditCtrls)m_Editors[m_HostControl.SelectedTab.Name];
        }
        
        void CodeEditor_Documentation(object sender, EventArgs e)
        {
            m_CurrentEditor.CodeEditor.SetText(m_CurrentEditor.Compiler.CompileSourceDocs(m_CurrentEditor.FilePath).Replace("\r","\r\n"));
        }
        void CodeEditor_FullSource(object sender, EventArgs e)
        {
            System.IO.TextReader tmpRead = new System.IO.StreamReader(m_CurrentEditor.FilePath);
            m_CurrentEditor.CodeEditor.SetText(tmpRead.ReadToEnd());
            tmpRead.Close();
        }
        void CodeEditor_Close(object sender, EventArgs e)
        {
            Close();
        }
        void CodeEditor_TextChanged(object sender, EventArgs e)
        {
            if (!m_HostControl.SelectedTab.Text.EndsWith("*"))
                m_HostControl.SelectedTab.Text += "*";
        }
        #endregion Events
        
        #region De/Constructur
        public FileEditors(TabControl HostControl) //, PropellentNet.SpinInterpreter CodeInterpreter)
        {
            
            //m_CodeInterpreter = CodeInterpreter;
            
            m_HostControl = HostControl;            
            m_HostControl.SelectedIndexChanged += new EventHandler(m_HostControl_SelectedIndexChanged);
            
            m_Editors = new Hashtable();
            
            NewEditor();
            
        }
        #endregion De/Constructur
        
        #region Public Functions
        public void New()
        {
            NewEditor();
        }
        public void Open()
        {
            System.Windows.Forms.OpenFileDialog tmpOFD = new OpenFileDialog();
            tmpOFD.CheckFileExists = true;
            tmpOFD.Multiselect = true;
            tmpOFD.Title = "Open Code File";
            tmpOFD.AddExtension = true;
            tmpOFD.Filter = "Propeller Source (*.spin)|*.spin|All Files (*.*)|*.*";

            if (tmpOFD.ShowDialog() == DialogResult.OK)
            {
                foreach (string tmpF in tmpOFD.FileNames)
                {
                    NewEditor(tmpF);
                }
            }
        }
        public void Open(string FileName)
        {
            NewEditor(FileName);
        }
        public void Save()
        {
            
            string fileName = "";
            
            if (m_CurrentEditor.FilePath == null)
            {
                System.Windows.Forms.SaveFileDialog tmpSFD = new SaveFileDialog();
                
                if (tmpSFD.ShowDialog() == DialogResult.OK)
                {
                    fileName = tmpSFD.FileName;
                }
                else
                    return;
                
            }
            else
                fileName = m_CurrentEditor.FilePath;
            
            Save(fileName);
            
        }
        public void Save(bool All)
        {


            string fileName = "";

            if (m_CurrentEditor.FilePath == null)
            {
                System.Windows.Forms.SaveFileDialog tmpSFD = new SaveFileDialog();

                if (tmpSFD.ShowDialog() == DialogResult.OK)
                {
                    fileName = tmpSFD.FileName;
                }
                else
                    return;

            }
            else
                fileName = m_CurrentEditor.FilePath;

            Save(fileName);

        }
        public void SaveAs()
        {
            
            string fileName = "";
            
            System.Windows.Forms.SaveFileDialog tmpSFD = new SaveFileDialog();
            
            if (tmpSFD.ShowDialog() == DialogResult.OK)
            {
                fileName = tmpSFD.FileName;
            }
            else
                return;
            
            Save(fileName);
            
        }
        public void Close()
        {
            if (m_HostControl.SelectedTab.Text.EndsWith("*"))
            {
                switch (MessageBox.Show("Would you like to save your changes?", "PropellentNet", MessageBoxButtons.YesNoCancel))
                {
                    case DialogResult.Yes:
                        Save();
                        break;
                    case DialogResult.Cancel:
                        return;
                    default:
                        break;
                }
            }
            
            m_Editors.Remove(m_CurrentEditor.ControlName);
            m_CurrentEditor.Compiler.Dispose();
            m_CurrentEditor.CodeEditor.Dispose();
            m_HostControl.TabPages[m_CurrentEditor.ControlName].Controls.Clear();
            m_HostControl.TabPages.Remove(m_HostControl.TabPages[m_CurrentEditor.ControlName]);

            if (m_Editors.Count == 0)
                NewEditor();
            
        }
        public void CloseAll()
        {

            string[] tmpNames = new string[m_Editors.Count];
            m_Editors.Keys.CopyTo(tmpNames, 0);
            
            foreach (string tmpStr in tmpNames)
            {
                EditCtrls tmpCtrl = (EditCtrls)m_Editors[tmpStr];

                if (m_HostControl.TabPages[tmpCtrl.ControlName].Text.EndsWith("*"))
                {
                    m_HostControl.SelectedTab =  m_HostControl.TabPages[tmpCtrl.ControlName];
                    switch (MessageBox.Show("Would you like to save your changes?", "PropellentNet", MessageBoxButtons.YesNoCancel))
                    {
                        case DialogResult.Yes:
                            Save();
                            break;
                        case DialogResult.Cancel:
                            return;
                        default:
                            break;
                    }
                }

                m_Editors.Remove(tmpCtrl.ControlName);
                tmpCtrl.Compiler.Dispose();
                tmpCtrl.CodeEditor.Dispose();
                m_HostControl.TabPages[tmpCtrl.ControlName].Controls.Clear();
                m_HostControl.TabPages.Remove(m_HostControl.TabPages[tmpCtrl.ControlName]);
            }
            
            if (m_Editors.Count == 0)
                NewEditor();
        }

        public void IdentifyHardware()
        {
            PropellentNet.Propellent.PropellerVerson tmpVer = m_CurrentEditor.Compiler.GetPropVersion();
        }
        public void UpdateStatus(TreeView HTree)
        {

            PropellentNet.Propellent.CompilerError tmpError = m_CurrentEditor.Compiler.CompileSource(m_CurrentEditor.FilePath, true);

            if (tmpError.Error != "")
                MessageBox.Show(tmpError.Error + "\r\n" + tmpError.ScrFile + "\r\n" + tmpError.ScrStart.ToString() + " : " + tmpError.ScrCount.ToString());

            System.Data.DataSet tmpDS = m_CurrentEditor.Compiler.GetPropSourceHierarchy();

            if (tmpDS == null)
                return;

            HTree.Nodes.Clear();
            
            if (tmpDS.Tables[0].Rows[0]["Filename"].ToString() == "")
                return;

            HTree.BeginUpdate();


            TreeNode currentNode = null;
            foreach (System.Data.DataRow tmpRow in tmpDS.Tables[0].Rows)
            {
                if (currentNode == null)
                {
                    currentNode = HTree.Nodes.Add(tmpRow["FileName"].ToString().Replace(".spin", ""));
                    currentNode.Tag = tmpRow["HLevel"];
                }
                else
                {
                    if ((int)currentNode.Tag > (int)tmpRow["HLevel"])
                    {
                        while ((int)currentNode.Tag > (int)tmpRow["HLevel"])
                        {
                            currentNode = currentNode.Parent;
                        }
                        currentNode = currentNode.Parent.Nodes.Add(tmpRow["FileName"].ToString().Replace(".spin", ""));
                        currentNode.Tag = tmpRow["HLevel"];
                    }
                    else if ((int)currentNode.Tag < (int)tmpRow["HLevel"])
                    {
                        currentNode = currentNode.Nodes.Add(tmpRow["FileName"].ToString().Replace(".spin", ""));
                        currentNode.Tag = tmpRow["HLevel"];
                    }
                    else
                    {
                        currentNode = currentNode.Parent.Nodes.Add(tmpRow["FileName"].ToString().Replace(".spin", ""));
                        currentNode.Tag = tmpRow["HLevel"];
                    }
                }


                currentNode.ImageIndex = (((PropellentNet.Propellent.FolderType)tmpRow["FolderType"]) == PropellentNet.Propellent.FolderType.library ? 0 : 1);
                currentNode.SelectedImageIndex = (((PropellentNet.Propellent.FolderType)tmpRow["FolderType"]) == PropellentNet.Propellent.FolderType.library ? 0 : 1);

            }

            HTree.ExpandAll();
            HTree.Nodes[0].EnsureVisible();
            HTree.EndUpdate();   
            
        }
        public void LoadRAM()
        {
            m_CurrentEditor.Compiler.CompileSource(m_CurrentEditor.FilePath, true);
            m_CurrentEditor.Compiler.DownloadToPropeller(null, PropellentNet.Propellent.LoadType.RAM);
        }
        public void LoadEEROM()
        {
            m_CurrentEditor.Compiler.CompileSource(m_CurrentEditor.FilePath, true);
            m_CurrentEditor.Compiler.DownloadToPropeller(null, PropellentNet.Propellent.LoadType.EEPROM_RUN);
        }
        #endregion Public Functions
        
        #region Private Functions
        private void Save(string fileName)
        {
            
            if (fileName.IndexOf('.') < 0)
                fileName += ".spin";
            
            string newControlName = fileName.Substring(fileName.LastIndexOf("\\") + 1, fileName.Length - fileName.LastIndexOf("\\") - 1);
            newControlName = newControlName.Remove(newControlName.LastIndexOf('.'));
            

            m_Editors.Remove(m_CurrentEditor.ControlName);
            m_Editors.Add(newControlName, m_CurrentEditor);
            
            m_CurrentEditor.ControlName = newControlName;
            
            System.IO.TextWriter tmpTW = (System.IO.TextWriter)new System.IO.StreamWriter(fileName);
            tmpTW.Write(m_CurrentEditor.CodeEditor.GetText());
            tmpTW.Close();
            
            m_CurrentEditor.FilePath = fileName;
            
            m_HostControl.SelectedTab.Name = m_CurrentEditor.ControlName;
            m_HostControl.SelectedTab.Text = m_CurrentEditor.ControlName;
            m_HostControl.SelectedTab.ToolTipText = m_CurrentEditor.FilePath;
            
            if (m_HostControl.SelectedTab.Text.EndsWith("*"))
                m_HostControl.SelectedTab.Text = m_HostControl.SelectedTab.Text.Replace("*", "");
            
        }
        
        private void NewEditor()
        {

            EditCtrls newCtrl = new EditCtrls();
            newCtrl.ControlName = "Untitile" + m_HoldUntitledCount.ToString();
            newCtrl.Compiler = new PropellentNet.Propellent(m_HostControl.Handle, true, null);
            newCtrl.CodeEditor = new CodeEditorContainer();

            m_HostControl.TabPages.Add(newCtrl.ControlName, newCtrl.ControlName, 1);
            m_HostControl.TabPages[newCtrl.ControlName].Controls.Add(newCtrl.CodeEditor);
            newCtrl.CodeEditor.Dock = DockStyle.Fill;

            newCtrl.CodeEditor.TextChanged += new CodeEditorContainer.exTextChanged(CodeEditor_TextChanged);
            newCtrl.CodeEditor.Close += new CodeEditorContainer.exClose(CodeEditor_Close);
            newCtrl.CodeEditor.FullSource += new CodeEditorContainer.exFullSource(CodeEditor_FullSource);
            newCtrl.CodeEditor.Documentation += new CodeEditorContainer.exDocumentation(CodeEditor_Documentation);

            m_Editors.Add(newCtrl.ControlName, newCtrl);
            m_CurrentEditor = newCtrl;

            m_HostControl.SelectedTab = m_HostControl.TabPages[newCtrl.ControlName];
            m_HostControl.SelectedTab.ToolTipText = "Holding Tab";
            
            m_HoldUntitledCount += 1;

        }
        private void NewEditor(string fileName)
        {

            EditCtrls newCtrl = new EditCtrls();


            string newControlName = fileName.Substring(fileName.LastIndexOf("\\") + 1, fileName.Length - fileName.LastIndexOf("\\") - 1);
            newControlName = newControlName.Remove(newControlName.LastIndexOf('.'));

            newCtrl.ControlName = newControlName;
            newCtrl.Compiler = new PropellentNet.Propellent(m_HostControl.Handle, true, null);
            newCtrl.CodeEditor = new CodeEditorContainer();
            newCtrl.FilePath = fileName;

            m_HostControl.TabPages.Add(newCtrl.ControlName, newCtrl.ControlName, 1);
            m_HostControl.TabPages[newCtrl.ControlName].Controls.Add(newCtrl.CodeEditor);
            newCtrl.CodeEditor.Dock = DockStyle.Fill;

            System.IO.TextReader tmpRead = new System.IO.StreamReader(fileName);
            newCtrl.CodeEditor.SetText(tmpRead.ReadToEnd());
            tmpRead.Close();

            m_HoldUntitledCount += 1;

            newCtrl.CodeEditor.TextChanged += new CodeEditorContainer.exTextChanged(CodeEditor_TextChanged);
            newCtrl.CodeEditor.Close += new CodeEditorContainer.exClose(CodeEditor_Close);
            newCtrl.CodeEditor.FullSource += new CodeEditorContainer.exFullSource(CodeEditor_FullSource);
            newCtrl.CodeEditor.Documentation += new CodeEditorContainer.exDocumentation(CodeEditor_Documentation);

            m_Editors.Add(newCtrl.ControlName, newCtrl);
            m_CurrentEditor = newCtrl;

            m_HostControl.SelectedTab = m_HostControl.TabPages[newCtrl.ControlName];
            m_HostControl.SelectedTab.ToolTipText = fileName;

        }
        #endregion Private Functions
        
    }
    
}